package com.june.junemplayer.service;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;

import static com.june.junemplayer.base.BaseApplication.getApplication;
import static com.june.junemplayer.service.MediaPlayerService.STOP_SONG;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.PixelFormat;
import android.os.Handler;
import android.os.IBinder;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.RelativeLayout;
import android.widget.TextView;

import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelStoreOwner;

import com.google.android.material.imageview.ShapeableImageView;
import com.june.junemplayer.R;
import com.june.junemplayer.controller.GlobalViewModelController;
import com.june.junemplayer.pojo.Song;
import com.june.junemplayer.utils.customView.RoundProgressView;

import java.io.IOException;

import de.hdodenhof.circleimageview.CircleImageView;

public class OverlayWindowView extends RelativeLayout implements View.OnClickListener, View.OnTouchListener {

    private MediaPlayerService mMediaPlayerService;
    private GlobalViewModelController mGlobalViewModelController;

    private PlayingListView mPlayingListView;


    private WindowManager mWindowManager;
    private WindowManager.LayoutParams mLayoutParams;

    private final int SCREEN_WIDTH;
    private final int SCREEN_HEIGHT;
    public OverlayWindowBallStatus mStatus;
    public boolean mIsAtLeft;

    private boolean mIsPlaying;

    private Context mContext;
    private View mView;

    private View mContentShellView;
    private View mContentView;

    private ShapeableImageView mImageView;
    private RelativeLayout mOverlaySong;
    private RelativeLayout mOverlayOperation;
    private RoundProgressView mProgressView;
    private TextView mSongTitle;
    private TextView mSongArtist;
    private CircleImageView mNextSong;
    private CircleImageView mForeSong;
    private CircleImageView mPlaySong;


    public OverlayWindowView(Context context) {
        this(context, null);
    }

    public OverlayWindowView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public OverlayWindowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;

        mGlobalViewModelController = new GlobalViewModelController((ViewModelStoreOwner) getApplication());

        mWindowManager = (WindowManager) mContext.getApplicationContext().getSystemService(Context.WINDOW_SERVICE);
        //设置好悬浮窗的参数
        mLayoutParams = new WindowManager.LayoutParams();
        mLayoutParams.width = MATCH_PARENT;
        mLayoutParams.height = 270;
        mLayoutParams.format = PixelFormat.RGBA_8888;
        mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
        mLayoutParams.flags = FLAG_NOT_TOUCH_MODAL | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_LAYOUT_NO_LIMITS ;

        //悬浮窗的开始位置，因为设置的是从左上角开始，所以屏幕左上角是x=0;y=0
        mLayoutParams.gravity = Gravity.START | Gravity.TOP;
        mLayoutParams.x = 0;
        mLayoutParams.y = 1800;

        SCREEN_WIDTH = mWindowManager.getDefaultDisplay().getWidth();
        SCREEN_HEIGHT = mWindowManager.getDefaultDisplay().getHeight();

        mPlayingListView=new PlayingListView(context);

        mView = LayoutInflater.from(context).inflate(R.layout.view_overlay_ball, this, true);
        mImageView = mView.findViewById(R.id.img_floating_button);
        mContentView = mView.findViewById(R.id.rl_ContentView);
        mContentShellView = mView.findViewById(R.id.rl_ContentShellView);

        mOverlaySong = mView.findViewById(R.id.Overlay_Song);
        mOverlayOperation = mView.findViewById(R.id.Overlay_Operation);
        mProgressView = mView.findViewById(R.id.pv_SongProgress);
        mSongTitle = mView.findViewById(R.id.tv_SongTitle);
        mSongArtist = mView.findViewById(R.id.tv_SongArtist);
        mNextSong = mView.findViewById(R.id.img_NextSong);
        mForeSong = mView.findViewById(R.id.img_ForeSong);
        mPlaySong = mView.findViewById(R.id.img_PlaySong);

        mView.setClickable(false);
        mContentShellView.setClickable(false);
        mNextSong.setOnClickListener(this);
        mForeSong.setOnClickListener(this);
        mPlaySong.setOnClickListener(this);
        mImageView.setOnTouchListener(this);
        mImageView.setOnClickListener(this);
        mOverlaySong.setOnClickListener(this);

        mStatus = OverlayWindowBallStatus.GONE;
        mIsAtLeft = true;
        mIsPlaying = false;

        Intent intent = new Intent(mContext, MediaPlayerService.class);
        mContext.bindService(intent, connectionMediaPlayerServiceConnection, Context.BIND_AUTO_CREATE);
    }

    private float mTouchScreenX, mTouchScreenY; // 触摸点在屏幕上的横纵坐标
    private float mLastY; // 上次触摸点的横纵坐标
    private float mTouchDownX, mTouchDownY; // 按下点的横纵坐标
    private float mMinWidth, mMaxWidth;// 可拖动的左右边界
    private float mMinHeight, mMaxHeight;// 可拖动的左右边界
    private long mTouchDownTime;
    private Handler mSlipHandler = new Handler();

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (v.getId()){
            case R.id.img_floating_button:
                return onTouchImageView(event);
            case R.id.Overlay_Song:
//                return onTouchCallPlayingListView(event);
        }
        return true;
    }

    private boolean onTouchCallPlayingListView(MotionEvent event) {

        mTouchScreenX = event.getRawX();
        mTouchScreenY = event.getRawY();
        mMinWidth = (mImageView.getWidth() >> 1) + 35;
        mMaxWidth = SCREEN_WIDTH - mImageView.getWidth() - 70;
        mMinHeight = (float) (SCREEN_HEIGHT * 0.1);
        mMaxHeight = (float) (SCREEN_HEIGHT * 0.9);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: // 手指按下
                mTouchDownTime = System.currentTimeMillis();
                mTouchDownX = mTouchScreenX;
                mTouchDownY = mTouchScreenY;
                break;
            case MotionEvent.ACTION_MOVE: // 手指移动
                if (mStatus == OverlayWindowBallStatus.ACTIVE || mStatus == OverlayWindowBallStatus.ABSORBING) {
                    return true;
                }
                mTouchScreenX -= mMinWidth;

                mTouchScreenX = mTouchScreenX < 0 ? 0 : Math.min(mTouchScreenX, mMaxWidth);
                mTouchScreenY = mTouchScreenY < mMinHeight ? mMinHeight : Math.min(mTouchScreenY, mMaxHeight);
                mImageView.setX(mTouchScreenX);
                // 更新视图的位置
                mLayoutParams.y = Math.round(mLayoutParams.y + mTouchScreenY - mLastY);
                mWindowManager.updateViewLayout(mView, mLayoutParams);
                break;
            case MotionEvent.ACTION_UP: // 手指松开
                //判断是否移动
                if (Math.abs(mTouchScreenX - mTouchDownX) < 3
                        && Math.abs(mTouchScreenY - mTouchDownY) < 3) {
                    //判断点击或长按
                    if (Math.abs(mTouchDownTime - System.currentTimeMillis()) < 300) {
                        mImageView.performClick();
                    } else {
                        mImageView.performLongClick();
                    }
                    return true;
                } else if (mStatus == OverlayWindowBallStatus.ACTIVE || mStatus == OverlayWindowBallStatus.ABSORBING) {
                    return true;
                }
                ObjectAnimator objectAnimator;
                if (mTouchScreenX >= (SCREEN_WIDTH >> 1)) {
                    objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", mTouchScreenX - mMinWidth, mMaxWidth);
                    setContentViewPosition(false);
                } else {
                    objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", mTouchScreenX - mMinWidth, 0);
                    setContentViewPosition(true);
                }
                mSlipHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        objectAnimator.setDuration(150).start();
                    }

                });
                mWindowManager.updateViewLayout(mView, mLayoutParams);
                break;
        }
        mLastY = mTouchScreenY;
        return true;
    }

    private boolean onTouchImageView(MotionEvent event) {
        mTouchScreenX = event.getRawX();
        mTouchScreenY = event.getRawY();
        mMinWidth = (mImageView.getWidth() >> 1) + 35;
        mMaxWidth = SCREEN_WIDTH - mImageView.getWidth() - 70;
        mMinHeight = (float) (SCREEN_HEIGHT * 0.1);
        mMaxHeight = (float) (SCREEN_HEIGHT * 0.9);

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: // 手指按下
                mTouchDownTime = System.currentTimeMillis();
                mTouchDownX = mTouchScreenX;
                mTouchDownY = mTouchScreenY;
                break;
            case MotionEvent.ACTION_MOVE: // 手指移动
                if (mStatus == OverlayWindowBallStatus.ACTIVE || mStatus == OverlayWindowBallStatus.ABSORBING) {
                    return true;
                }
                mTouchScreenX -= mMinWidth;

                mTouchScreenX = mTouchScreenX < 0 ? 0 : Math.min(mTouchScreenX, mMaxWidth);
                mTouchScreenY = mTouchScreenY < mMinHeight ? mMinHeight : Math.min(mTouchScreenY, mMaxHeight);
                mImageView.setX(mTouchScreenX);
                // 更新视图的位置
                mLayoutParams.y = Math.round(mLayoutParams.y + mTouchScreenY - mLastY);
                mWindowManager.updateViewLayout(mView, mLayoutParams);
                break;
            case MotionEvent.ACTION_UP: // 手指松开
                //判断是否移动
                if (Math.abs(mTouchScreenX - mTouchDownX) < 3
                        && Math.abs(mTouchScreenY - mTouchDownY) < 3) {
                    //判断点击或长按
                    if (Math.abs(mTouchDownTime - System.currentTimeMillis()) < 300) {
                        mImageView.performClick();
                    } else {
                        mImageView.performLongClick();
                    }
                    return true;
                } else if (mStatus == OverlayWindowBallStatus.ACTIVE || mStatus == OverlayWindowBallStatus.ABSORBING) {
                    return true;
                }
                ObjectAnimator objectAnimator;
                if (mTouchScreenX >= (SCREEN_WIDTH >> 1)) {
                    objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", mTouchScreenX - mMinWidth, mMaxWidth);
                    setContentViewPosition(false);
                } else {
                    objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", mTouchScreenX - mMinWidth, 0);
                    setContentViewPosition(true);
                }
                mSlipHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        objectAnimator.setDuration(150).start();
                    }

                });
                mWindowManager.updateViewLayout(mView, mLayoutParams);
                break;
        }
        mLastY = mTouchScreenY;
        return true;
    }

    private void setContentViewPosition(boolean b) {
        mIsAtLeft = b;
        if (mIsAtLeft) {
            LayoutParams ShellParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            ShellParams.setMargins(115, 0, 0, 0);
            mContentShellView.setLayoutParams(ShellParams);
            LayoutParams ContentParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            ContentParams.setMargins(-100, 0, 0, 0);
            mContentView.setLayoutParams(ContentParams);
            //还需要设置内容的左右间距
            LayoutParams OverlaySongParams = new LayoutParams(700, WRAP_CONTENT);
            OverlaySongParams.setMargins(210, 15, 0, 0);
            mOverlaySong.setLayoutParams(OverlaySongParams);
            LayoutParams OverlayOperationParams = new LayoutParams(525, MATCH_PARENT);
            OverlayOperationParams.setMargins(SCREEN_WIDTH - mOverlayOperation.getWidth() - 35, 0, 35, 0);
            mOverlayOperation.setLayoutParams(OverlayOperationParams);
        } else {
            LayoutParams ShellParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            ShellParams.setMargins(0, 0, 115, 0);
            mContentShellView.setLayoutParams(ShellParams);
            LayoutParams ContentParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            ContentParams.setMargins(0, 0, -100, 0);
            mContentView.setLayoutParams(ContentParams);
            LayoutParams OverlayOperationParams = new LayoutParams(525, MATCH_PARENT);
            OverlayOperationParams.setMargins(SCREEN_WIDTH - mOverlayOperation.getWidth() - 300, 0, 35, 0);
            mOverlayOperation.setLayoutParams(OverlayOperationParams);
            LayoutParams OverlaySongParams = new LayoutParams(700, WRAP_CONTENT);
            OverlaySongParams.setMargins(100, 15, 0, 0);
            mOverlaySong.setLayoutParams(OverlaySongParams);
        }
    }

    @Override
    public void onClick(View v) {
        Log.i("JuneProcedure", getTag() + "------onClick() parameter = " + v.getId() +"------");
        switch (v.getId()) {
            case R.id.img_floating_button:
                onClickShowOrHide();
                break;
            case R.id.img_ForeSong:
                PlaySong(mGlobalViewModelController.getNextInPlayingList());
//                mMediaPlayerService.changeSongState(MediaPlayerService.FORE_SONG);
                break;
            case R.id.img_NextSong:
                mMediaPlayerService.changeSongState(MediaPlayerService.NEXT_SONG);
                break;
            case R.id.img_PlaySong:
                if (mIsPlaying) {
                    mPlaySong.setImageResource(R.drawable.ic_stop_song);
                    mMediaPlayerService.changeSongState(STOP_SONG);
                } else {
                    mPlaySong.setImageResource(R.drawable.ic_play_song);
                    mMediaPlayerService.changeSongState(MediaPlayerService.START_SONG);
                }
                mIsPlaying = !mIsPlaying;
                break;
        }
    }

    private void onClickShowOrHide() {
        Log.i("JuneProcedure", getTag() + "------onClickShowOrHide() start:status = " + mStatus +"------");
        ObjectAnimator mContentViewAnimation;
        ObjectAnimator mImageViewAnimationClockwise = ObjectAnimator.ofFloat(mImageView, "rotation",
                0f, 120f, 240f, 360f);
        ObjectAnimator mImageViewAnimationAntiClockwise = ObjectAnimator.ofFloat(mImageView, "rotation",
                360f, 240f, 120f, 0);
        switch (mStatus) {
            case ABSORBING:
                mStatus = OverlayWindowBallStatus.INACTIVE;
                break;
            case INACTIVE:
                mStatus = OverlayWindowBallStatus.ACTIVE;
                mContentShellView.setVisibility(View.VISIBLE);
                mContentView.setVisibility(VISIBLE);
                if (mIsAtLeft) {
                    mContentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationX",
                            mContentView.getPaddingStart() - mContentView.getMeasuredWidth(),
                            mContentView.getPaddingEnd());
                    mImageViewAnimationClockwise.setDuration(300).start();
                } else {
                    mContentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationX",
                            mContentView.getPaddingStart() + mContentView.getMeasuredWidth(),
                            mContentView.getPaddingEnd());
                    mImageViewAnimationAntiClockwise.setDuration(300).start();
                }

                mContentViewAnimation.removeAllListeners();
                mContentViewAnimation.setDuration(300).start();
                break;
            case ACTIVE:
                mStatus = OverlayWindowBallStatus.INACTIVE;
                if (mIsAtLeft) {
                    mContentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationX",
                            mContentView.getPaddingEnd(),
                            mContentView.getPaddingStart() - mContentView.getMeasuredWidth());
                    mContentViewAnimation.setDuration(300).start();
                    mImageViewAnimationAntiClockwise.setDuration(300).start();
                } else {
                    mContentViewAnimation = ObjectAnimator.ofFloat(mContentView, "translationX",
                            mContentView.getPaddingEnd(),
                            mContentView.getPaddingStart() + mContentView.getMeasuredWidth());
                    mContentViewAnimation.setDuration(300).start();
                    mImageViewAnimationClockwise.setDuration(300).start();
                }
                mContentViewAnimation.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mContentShellView.setVisibility(View.GONE);
                        mContentView.setVisibility(View.GONE);
                    }
                });
                break;
        }
        Log.i("JuneProcedure", getTag() + "------onClickShowOrHide() end:status = " + mStatus +"------");
    }

    public String getTag() {
        return "OverlayWindowView";
    }

    private ServiceConnection connectionMediaPlayerServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            mMediaPlayerService = ((MediaPlayerService.MediaPlayerServiceBinder) iBinder).getService();
            Log.d("JuneProcedureLog", getTag() + "----onServiceConnect----OverlayWindowService");
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            Log.d("JuneProcedureLog", getTag() + "----onServiceDisconnected----OverlayWindowService");
        }
    };

    public void show() {
        mWindowManager.addView(mView, mLayoutParams);
        mStatus=OverlayWindowBallStatus.INACTIVE;
    }

    public void hide() {
        mWindowManager.removeView(mView);
    }

    public void PlaySong(Song song) {
        mSongTitle.setText(song.getTitle());
        mSongArtist.setText(song.getArtist());
        mIsPlaying = true;
        mPlaySong.setImageResource(R.drawable.ic_play_song);
        //如果正在播放另一首歌，则首先暂停，然后reset，然后再prepare
        try {
            mMediaPlayerService.prepareSong(song);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public enum OverlayWindowBallStatus {
        /**
         * 激活状态，显示操作框
         */
        ACTIVE,
        /**
         * 吸附状态，不显示操作框，悬浮球显示一半
         */
        ABSORBING,
        /**
         * 未激活状态，不显示操作框
         */
        INACTIVE,
        /**
         * 悬浮窗未消失状态
         */
        GONE;
    }
}